﻿using System;
using System.Web;
using System.Linq;
using cludg.Infrastructure.Core.Attributes;
using System.Web.Mvc;
using nsadv.Statistic.Domain;
using nsadv.Statistic.Services;
using nsadv.Statistic.Web.Security;
using nsadv.Statistic.Web.ViewModels;
using System.Collections.Generic;

namespace nsadv.Statistic.Web.Controllers
{
	public class StatisticController : BaseController
	{
		[Dependency]
		public Services.Statistic Statistic { get; set; }

		[Dependency]
		public Classifier<Platform> Platforms { get; set; }

		[Dependency]
		public Classifier<Campaign> Campaigns { get; set; }

		[Dependency]
		public Classifier<Place> Places { get; set; }

		[Dependency]
		public Classifier<Banner> Banners { get; set; }

		public ActionResult Send()
		{
			return View();
		}

		[HttpPost]
		[ValidateInput(false)]
		public ActionResult Send(string p, bool errors = false)
		{
			if (errors)
			{
				try
				{
					Statistic.ParseStatistic(p);
				}
				catch (Exception e)
				{
					throw new HttpException(98, e.Message);
				}
			}
			else
			{
				if (!Statistic.TryParseStatistic(p))
					throw new HttpException(98, "Ошибка формата");
			}

			return new EmptyResult();
		}

		#region Cabinet
		public ActionResult Cabinet(bool? archive)
		{
			var model = CreateModel<CabinetModel>();
			model.NavigationMenu.SetActiveItem(archive ?? false ? "ArchiveBanners" : "ActiveBanners");

			if (model.SecurityInfo.User.Is(UserRole.None))
				return RedirectToAction("Logon", "Account", null);

			model.Archive = archive ?? false;

			model.ShowAllCampaigns = true;
			model.ShowAllPlatforms = true;
			model.ShowAllPlaces = true;

			var platforms = Platforms.All;
			model.Platforms.AddRange(platforms);

			if (model.SecurityInfo.User.Is(UserRole.Place))
			{
				model.ShowPlaces = false;
			}
			else
			{
				model.ShowPlaces = true;
				var places = Places.All;
				model.Places.AddRange(places);
			}

			var campaigns = Campaigns.All;
			if (model.SecurityInfo.User.Is(UserRole.Advertiser))
			{
				campaigns = campaigns.Where(x => x.Advertiser.Id == model.SecurityInfo.User.Advertiser.Id);
				//model.ShowAllCampaigns = false;
			}
			model.Campaigns.AddRange(campaigns);

			return View(model);
		}

		public ActionResult Details(StatisticParams model)
		{
			if (CurrentUserIs(UserRole.None))
				return AccessDenied("Нет прав для просмотра");

			var details = new StatisticDetailsModel 
				{
					PlaceId = model.PlaceId,
					PlatformId = model.PlatformId
				};

			string advertiserId = null;
			if (CurrentUserIs(UserRole.Advertiser))
				advertiserId = GetCurrentUser().Advertiser.Id;

			string placeId = null;
			if (CurrentUserIs(UserRole.Place))
				placeId = GetCurrentUser().Place.Id;
			else
				placeId = model.PlaceId;

			var statistic = Statistic.Query(
				advertiserId,
				placeId,
				model.PlatformId,
				model.CampaignId,
				!model.Archive);

			// Печально, но это в hibernate linq не пройдет похоже =)
			//var banners = statistic.GroupBy<StatisticItem, Banner, StatisticDetailRow>(
			//       item => item.Banner,
			//       (banner, items) => new StatisticDetailRow
			//           {
			//               Banner = banner,
			//               Clicks = items.Where(x => x.EventId == (int)EventType.Click).Count(),
			//               Shows = items.Where(x => x.EventId == (int)EventType.Show).Count()
			//           });

			var banners = Banners.All;
			if (!String.IsNullOrEmpty(model.CampaignId))
				banners = banners.Where(x => x.Campaign.Id == model.CampaignId);
			if (!String.IsNullOrEmpty(advertiserId))
				banners = banners.Where(x => x.Campaign.Advertiser.Id == advertiserId);
			if (model.Archive)
				banners = banners.Where(x => !x.Campaign.IsActive);
			else
				banners = banners.Where(x => x.Campaign.IsActive);

			Dictionary<string, int> clickPlatformDir = new Dictionary<string, int>();
			//int allClicks = 0;
			Dictionary<string, int> showPlatformDir = new Dictionary<string, int>();
			//int allShows = 0;

			foreach (var banner in banners)
			{
				var bannerStat = statistic.Where(x => x.Banner.Id == banner.Id);

				var clicks = bannerStat.Where(x => x.EventId == (int)EventType.Click).Sum(x => x.Count);
				var expands = bannerStat.Where(x => x.EventId == (int)EventType.ShowFullscreen).Sum(x => x.Count);
				var shows = bannerStat.Where(x => x.EventId == (int)EventType.Show).Sum(x => x.Count);

				var firstBanner = bannerStat.FirstOrDefault();
				if (firstBanner != null) {
					if (clickPlatformDir.ContainsKey(firstBanner.Platform.Id))
						clickPlatformDir[firstBanner.Platform.Id] += clicks;
					else
						clickPlatformDir.Add(firstBanner.Platform.Id, clicks);

					if (showPlatformDir.ContainsKey(firstBanner.Platform.Id))
						showPlatformDir[firstBanner.Platform.Id] += shows;
					else
						showPlatformDir.Add(firstBanner.Platform.Id, shows);
				}

				var row = new StatisticBannerDetailRow
							{
								Banner = banner,
								Clicks = clicks,
								Expands = expands,
								Shows = shows
							};

				details.BannerRows.Add(row);
			}

			var platforms = Platforms.All;

			// NOTE: В целях оптимизации с учтом, что у нас одна платформа, подсчет статистики по каждой платформе
			// не делаем, а просто собираем все показатели
			if (platforms.Count() > 0)
			{
				foreach (var platform in platforms)
				{
					var row = new StatisticPlatformDetailRow
								{
									Platform = platform,
									Clicks = clickPlatformDir.ContainsKey(platform.Id) ? clickPlatformDir[platform.Id] : 0,
									Shows = showPlatformDir.ContainsKey(platform.Id) ? showPlatformDir[platform.Id] : 0,
								};
					details.PlatformRows.Add(row);
				}
				//var row = new StatisticPlatformDetailRow
				//            {
				//                Platform = platforms.FirstOrDefault(),
				//                Clicks = allClicks,
				//                Shows = allShows
				//            };
				//details.PlatformRows.Add(row);
			}

			// TODO: Тут вместо model.PlatformId было null. Так и задумано, или баг?
			//var platformStatistic = Statistic.Query(advertiserId, placeId, model.PlatformId, model.CampaignId, !model.Archive);

			//foreach (var platform in platforms)
			//{
			//    var platformStat = platformStatistic.Where(x => x.Platform.Id == platform.Id);
			//    var row = new StatisticPlatformDetailRow
			//                {
			//                    Platform = platform,
			//                    Clicks = platformStat.Where(x => x.EventId == (int)EventType.Click).Sum(x => x.Count),
			//                    Shows = platformStat.Where(x => x.EventId == (int)EventType.Show).Sum(x => x.Count)
			//                };
			//    details.PlatformRows.Add(row);
			//}

			return PartialView("StatisticDetails", details);
		} 
		#endregion

		#region Banner periodical details

		public ActionResult BannerPeriodical(string id, string platformId, string placeId)
		{
			var model = CreateModel<BannerPeriodicalModel> ();

			if (model.SecurityInfo.User.Is(UserRole.None))
				return RedirectToAction("Logon", "Account", null);

			var banner = Banners.ById(id);
			if (banner == null)
			{
				ShowMessage(MessageType.Error, string.Format("Баннера с ИД '{0}' не существует.", id));
				return RedirectToAction("Cabinet");
			}

			model.Banner = banner;
			if (!string.IsNullOrWhiteSpace(platformId)) 
			{		
				model.Platform = Platforms.ById(platformId);
			}

			if (CurrentUserIs(UserRole.Place))
				model.Place = GetCurrentUser().Place;
			else
				if (!string.IsNullOrWhiteSpace(placeId))
					model.Place = Places.ById(placeId);

			return View(model);
		}

		[HttpPost]
		public ActionResult BannerPeriodicalDetails(BannerPeriodicalParams model)
		{
			if (CurrentUserIs(UserRole.None))
				return AccessDenied("Нет прав для просмотра");

			var details = new BannerPeriodicalDetailsModel();
			details.Groupping = model.Groupping;

			var banner = Banners.ById(model.BannerId);
			Platform platform = null;
			if (!string.IsNullOrWhiteSpace(model.PlatformId))
			{
				platform = Platforms.ById(model.PlatformId);
			}

			Advertiser advertiser = null;
			if (CurrentUserIs(UserRole.Advertiser))
				advertiser = GetCurrentUser().Advertiser;

			Place place = null;
			if (CurrentUserIs(UserRole.Place))
				place = GetCurrentUser().Place;
			else
				if (!string.IsNullOrWhiteSpace(model.PlaceId))
					place = Places.ById(model.PlaceId);


			if (banner != null)
			{
				var items = Statistic.BannerPeriodical(banner, platform, advertiser, place, model.Groupping, model.From, model.To);
				details.BannerRows.AddRange(items);
			}

			return PartialView(details);
		}

		#endregion
	}
}
